from abc import ABC, abstractmethod
from datetime import datetime, timedelta
from typing import List, Optional


# 抽象基类
class LibraryItem(ABC):
    def __init__(self, title: str, item_id: str):
        self.title = title
        self.item_id = item_id
        self.is_borrowed = False
        self.borrowed_date: Optional[datetime] = None
        self.due_date: Optional[datetime] = None

    @abstractmethod
    def get_loan_period(self) -> int:
        """获取借阅期限（天数）"""
        pass

    def borrow(self) -> bool:
        """借阅物品"""
        if not self.is_borrowed:
            self.is_borrowed = True
            self.borrowed_date = datetime.now()
            self.due_date = self.borrowed_date + timedelta(days=self.get_loan_period())
            return True
        return False

    def return_item(self) -> bool:
        """归还物品"""
        if self.is_borrowed:
            self.is_borrowed = False
            self.borrowed_date = None
            self.due_date = None
            return True
        return False

    def is_overdue(self) -> bool:
        """检查是否逾期"""
        if self.is_borrowed and self.due_date:
            return datetime.now() > self.due_date
        return False


class Book(LibraryItem):
    def __init__(self, title: str, item_id: str, author: str, isbn: str):
        super().__init__(title, item_id)
        self.author = author
        self.isbn = isbn

    def get_loan_period(self) -> int:
        return 30  # 图书借阅期限为30天

    def __str__(self):
        status = "已借出" if self.is_borrowed else "可借阅"
        return f"图书: {self.title} (作者: {self.author}, ISBN: {self.isbn}) - {status}"


class Magazine(LibraryItem):
    def __init__(self, title: str, item_id: str, issue: str):
        super().__init__(title, item_id)
        self.issue = issue

    def get_loan_period(self) -> int:
        return 7  # 杂志借阅期限为7天

    def __str__(self):
        status = "已借出" if self.is_borrowed else "可借阅"
        return f"杂志: {self.title} (期号: {self.issue}) - {status}"


class Member:
    def __init__(self, name: str, member_id: str):
        self.name = name
        self.member_id = member_id
        self.borrowed_items: List[LibraryItem] = []

    def borrow_item(self, item: LibraryItem) -> bool:
        if item.borrow():
            self.borrowed_items.append(item)
            return True
        return False

    def return_item(self, item: LibraryItem) -> bool:
        if item in self.borrowed_items and item.return_item():
            self.borrowed_items.remove(item)
            return True
        return False

    def get_overdue_items(self) -> List[LibraryItem]:
        return [item for item in self.borrowed_items if item.is_overdue()]


class Library:
    def __init__(self):
        self.items: List[LibraryItem] = []
        self.members: List[Member] = []

    def add_item(self, item: LibraryItem):
        self.items.append(item)

    def add_member(self, member: Member):
        self.members.append(member)

    def find_item(self, item_id: str) -> Optional[LibraryItem]:
        for item in self.items:
            if item.item_id == item_id:
                return item
        return None

    def find_member(self, member_id: str) -> Optional[Member]:
        for member in self.members:
            if member.member_id == member_id:
                return member
        return None


# 使用示例
library = Library()

# 添加图书和杂志
book1 = Book("Python编程入门", "B001", "张三", "978-1234567890")
book2 = Book("机器学习实战", "B002", "李四", "978-0987654321")
magazine1 = Magazine("科技新时代", "M001", "2023年10月刊")

library.add_item(book1)
library.add_item(book2)
library.add_item(magazine1)

# 添加会员
member1 = Member("王五", "M001")
library.add_member(member1)

# 借阅操作
print("=== 图书馆物品信息 ===")
for item in library.items:
    print(item)

print("\n=== 借阅操作 ===")
member = library.find_member("M001")
item = library.find_item("B001")

if member and item:
    if member.borrow_item(item):
        print(f"{member.name} 成功借阅了 {item.title}")
    else:
        print(f"{item.title} 借阅失败")

print("\n=== 借阅后状态 ===")
for item in library.items:
    print(item)
